package org.jeecg.modules.mes.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.mes.entity.*;
import org.jeecg.modules.mes.mapper.MesProductionPlanMapper;
import org.jeecg.modules.mes.service.*;
import org.jeecg.modules.mes.vo.MesCreatePlanFromTemplateVO;
import org.jeecg.modules.mes.vo.MesCustomPlanCreateVO;
import org.jeecg.modules.mes.vo.MesProductionPlanVO;
import org.jeecg.modules.mes.vo.MesMergedPlanCreateVO;
import org.jeecg.modules.mes.vo.MesProductionPlanDetailVO;
import org.jeecg.modules.system.entity.SysEmployee;
import org.jeecg.modules.system.service.ISysEmployeeService;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.service.ISysAnnouncementService;
import org.jeecg.modules.oms.service.IProductSalesOrderService;
import org.jeecg.modules.oms.entity.ProductSalesOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Description: 生产计划管理
 * @Author: jeecg-boot
 * @Date: 2025-01-21
 * @Version: V1.0
 */
@Service
@Slf4j
public class MesProductionPlanServiceImpl extends ServiceImpl<MesProductionPlanMapper, MesProductionPlan> implements IMesProductionPlanService {

    @Autowired
    private IMesProductionTemplateService templateService;

    @Autowired
    private IMesProductionPlanTaskService planTaskService;

    @Autowired
    private IMesEmployeeWorkTypeService employeeWorkTypeService;

    @Autowired
    private IProductSalesOrderService productSalesOrderService;

    @Autowired
    private IMesProductionPlanOrderDetailService orderDetailService;
    @Autowired
    private IMesTaskParticipantService taskParticipantService;
    @Autowired
    private IMesProductionPlanOrderDetailService planOrderDetailService;

    @Autowired
    private ISysAnnouncementService sysAnnouncementService;

    @Autowired
    private IMesPieceRateStandardService pieceRateStandardService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createPlanFromTemplate(MesCreatePlanFromTemplateVO createVO) {
        // 1. 验证模板是否存在
        MesProductionTemplate template = templateService.getById(createVO.getTemplateId());
        if (template == null) {
            throw new JeecgBootException("生产模板不存在");
        }
        if (template.getStatus() != 1) {
            throw new JeecgBootException("生产模板已停用");
        }

        // 2. 创建生产计划主记录
        MesProductionPlan plan = new MesProductionPlan();
        plan.setPlanNo(generatePlanNo());
        plan.setPlanName(createVO.getPlanName());
        plan.setOrderId(createVO.getOrderId());
        plan.setOrderNo(createVO.getOrderNo());
        plan.setTemplateId(createVO.getTemplateId());
        plan.setTemplateName(template.getTemplateName());
        plan.setPlanType(1); // 模板生成
        plan.setPlanStartDate(createVO.getPlanStartDate());
        plan.setPlanEndDate(createVO.getPlanEndDate());
        plan.setPlanQuantity(createVO.getPlanQuantity());
        plan.setActualQuantity(0);
        plan.setStatus(0); // 待审核
        plan.setPlanManager(createVO.getPlanManager());
        plan.setPriority(createVO.getPriority() != null ? createVO.getPriority() : 2);
        plan.setRemark(createVO.getRemark());

        this.save(plan);

        // 3. 使用前端传递的工种任务配置创建任务
        if (createVO.getTasks() != null && !createVO.getTasks().isEmpty()) {
            // 如果有选中的产品明细，按产品明细生成任务
            if (createVO.getOrderDetailIds() != null && !createVO.getOrderDetailIds().isEmpty()) {
                List<Map<String, Object>> orderDetails = orderDetailService.getOrderDetailsByIds(createVO.getOrderDetailIds());

                for (Map<String, Object> orderDetail : orderDetails) {
                    for (MesCreatePlanFromTemplateVO.TemplateTaskVO taskVO : createVO.getTasks()) {
                        MesProductionPlanTask task = new MesProductionPlanTask();
                        task.setPlanId(plan.getId());
                        task.setWorkTypeId(taskVO.getWorkTypeId());
                        task.setWorkTypeCode(taskVO.getWorkTypeCode());
                        task.setWorkTypeName(taskVO.getWorkTypeName());
                        task.setSequence(taskVO.getSequence());
                        task.setTaskQuantity((Integer) orderDetail.get("planQuantity")); // 使用产品明细的数量
                        task.setCompletedQuantity(0);
                        task.setPlanStartDate(createVO.getPlanStartDate());
                        task.setPlanEndDate(createVO.getPlanEndDate());
                        task.setStatus(0); // 待领取
                        task.setPieceRateStandardId(taskVO.getPieceRateStandardId());
                        task.setRemark(taskVO.getRemark());

                        // 设置协作类型、允许部分领取、最大参与人数
                        task.setCollaborationType(taskVO.getCollaborationType() != null ? taskVO.getCollaborationType() : 0);
                        task.setMaxParticipants(taskVO.getMaxParticipants() != null ? taskVO.getMaxParticipants() : 1);
                        task.setAllowPartialClaim(taskVO.getAllowPartialClaim() != null ? (taskVO.getAllowPartialClaim() ? 1 : 0) : 1);
                        task.setCurrentParticipants(0); // 初始参与人数为0

                        // 设置产品明细关联信息
                        task.setOrderDetailId((String) orderDetail.get("orderDetailId"));
                        task.setOrderNo((String) orderDetail.get("orderNo"));
                        task.setProductInfo((String) orderDetail.get("productInfo"));
                        task.setProductCode((String) orderDetail.get("productCode"));
                        task.setProductName((String) orderDetail.get("productName"));
                        task.setProductSpec((String) orderDetail.get("productSpec"));

                        planTaskService.save(task);
                    }
                }

                log.info("基于模板创建生产计划成功，计划ID：{}, 计划编号：{}, 产品明细数量：{}, 工种数量：{}, 生成任务数量：{}",
                        plan.getId(), plan.getPlanNo(), orderDetails.size(), createVO.getTasks().size(),
                        orderDetails.size() * createVO.getTasks().size());
            }
        }

        return plan.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createCustomPlan(MesCustomPlanCreateVO createVO) {
        // 1. 创建生产计划主记录
        MesProductionPlan plan = new MesProductionPlan();
        plan.setPlanNo(generatePlanNo());
        plan.setPlanName(createVO.getPlanName());
        plan.setOrderId(createVO.getOrderId());
        plan.setOrderNo(createVO.getOrderNo());
        plan.setPlanType(2); // 自定义创建
        plan.setPlanStartDate(createVO.getPlanStartDate());
        plan.setPlanEndDate(createVO.getPlanEndDate());
        plan.setPlanQuantity(createVO.getPlanQuantity());
        plan.setActualQuantity(0);
        plan.setStatus(0); // 待审核
        plan.setPlanManager(createVO.getPlanManager());
        plan.setPriority(createVO.getPriority() != null ? createVO.getPriority() : 2);
        plan.setRemark(createVO.getRemark());

        this.save(plan);

        // 设置订单明细信息
        if (createVO.getOrderDetailId() != null && !createVO.getOrderDetailId().trim().isEmpty()) {
            plan.setOrderDetailId(createVO.getOrderDetailId());
        }
        if (createVO.getProductInfo() != null && !createVO.getProductInfo().trim().isEmpty()) {
            plan.setProductInfo(createVO.getProductInfo());
        }

        // 2. 创建自定义工种任务
        if (createVO.getTasks() != null && !createVO.getTasks().isEmpty()) {
            // 如果有选中的产品明细，按产品明细生成任务
            if (createVO.getOrderDetailIds() != null && !createVO.getOrderDetailIds().isEmpty()) {
                List<Map<String, Object>> orderDetails = orderDetailService.getOrderDetailsByIds(createVO.getOrderDetailIds());

                for (Map<String, Object> orderDetail : orderDetails) {
                    for (MesCustomPlanCreateVO.CustomPlanTaskVO taskVO : createVO.getTasks()) {
                        MesProductionPlanTask task = new MesProductionPlanTask();
                        task.setPlanId(plan.getId());
                        task.setWorkTypeId(taskVO.getWorkTypeId());
                        task.setWorkTypeCode(taskVO.getWorkTypeCode());
                        task.setWorkTypeName(taskVO.getWorkTypeName());
                        task.setSequence(taskVO.getSequence());
                        task.setTaskQuantity((Integer) orderDetail.get("planQuantity")); // 使用产品明细的数量
                        task.setCompletedQuantity(0);
                        task.setPlanStartDate(createVO.getPlanStartDate());
                        task.setPlanEndDate(createVO.getPlanEndDate());
                        task.setStatus(0); // 待领取
                        task.setRemark(taskVO.getRemark());
                        task.setPieceRateStandardId(taskVO.getPieceRateStandardId());

                        // 设置协作类型、允许部分领取、最大参与人数
                        task.setCollaborationType(taskVO.getCollaborationType() != null ? taskVO.getCollaborationType() : 0);
                        task.setMaxParticipants(taskVO.getMaxParticipants() != null ? taskVO.getMaxParticipants() : 1);
                        task.setAllowPartialClaim(taskVO.getAllowPartialClaim() != null ? (taskVO.getAllowPartialClaim() ? 1 : 0) : 1);
                        task.setCurrentParticipants(0); // 初始参与人数为0

                        // 设置产品明细关联信息
                        task.setOrderDetailId((String) orderDetail.get("orderDetailId"));
                        task.setOrderNo((String) orderDetail.get("orderNo"));
                        task.setProductInfo((String) orderDetail.get("productInfo"));
                        task.setProductCode((String) orderDetail.get("productCode"));
                        task.setProductName((String) orderDetail.get("productName"));
                        task.setProductSpec((String) orderDetail.get("productSpec"));

                        planTaskService.save(task);
                    }
                }

                log.info("自定义创建生产计划成功，计划ID：{}, 计划编号：{}, 产品明细数量：{}, 工种数量：{}, 生成任务数量：{}",
                        plan.getId(), plan.getPlanNo(), orderDetails.size(), createVO.getTasks().size(),
                        orderDetails.size() * createVO.getTasks().size());
            }
        }

        return plan.getId();
    }

    @Override
    public List<MesProductionPlanTask> getAvailableTasks(String employeeId, String workTypeId) {
        LambdaQueryWrapper<MesProductionPlanTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MesProductionPlanTask::getStatus, 0); // 待领取状态

        if (workTypeId != null && !workTypeId.isEmpty()) {
            queryWrapper.eq(MesProductionPlanTask::getWorkTypeId, workTypeId);
        }

        List<MesProductionPlanTask> allTasks = planTaskService.list(queryWrapper);

        // 过滤员工有权限的工种任务
        return allTasks.stream()
                .filter(task -> checkEmployeeWorkTypePermission(employeeId, task.getWorkTypeId()))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void claimTask(String taskId, String employeeId) {
        MesProductionPlanTask task = planTaskService.getById(taskId);
        if (task == null) {
            throw new JeecgBootException("任务不存在");
        }

        if (task.getStatus() != 0) {
            throw new JeecgBootException("任务状态不允许领取");
        }

        // 检查员工是否有权限领取该工种任务
        if (!checkEmployeeWorkTypePermission(employeeId, task.getWorkTypeId())) {
            throw new JeecgBootException("员工没有该工种权限");
        }

        // 更新任务状态
        task.setStatus(1); // 已领取 待完善

        planTaskService.updateById(task);

        // 更新计划状态
        updatePlanProgress(task.getPlanId());

        log.info("员工{}成功领取任务{}", employeeId, taskId);
    }

    @Override
    public List<MesProductionPlanTask> getMyTasks(String employeeId) {
        // 通过参与者表获取员工的任务
        return planTaskService.getEmployeeTasks(employeeId, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvePlan(String planId, Boolean approved, String remark) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (plan.getStatus() != 0) {
            throw new JeecgBootException("计划状态不允许审核");
        }

        if (approved) {
            plan.setStatus(1); // 已审核
        } else {
            plan.setStatus(6); // 已取消
        }

        if (remark != null && !remark.isEmpty()) {
            plan.setRemark(plan.getRemark() + "\n审核意见：" + remark);
        }

        this.updateById(plan);

        log.info("生产计划{}审核完成，结果：{}", planId, approved ? "通过" : "拒绝");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void issuePlan(String planId) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (plan.getStatus() != 1) {
            throw new JeecgBootException("只有已审核的计划才能下发");
        }

        plan.setStatus(2); // 已下发
        this.updateById(plan);
        // 获取当前用户上下文信息，传递给异步方法
        String currentTenantId = null;
        String currentUserId = null;
        try {
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if (loginUser != null) {
                currentTenantId = String.valueOf(loginUser.getRelTenantIds());
                currentUserId = loginUser.getId();
            }
        } catch (Exception e) {
            log.warn("获取当前用户信息失败，将使用默认值: {}", e.getMessage());
        }

        // 下发后，根据任务的工种类型，异步通知对应工种的员工
        final String tenantId = currentTenantId;
        final String userId = currentUserId;
        CompletableFuture.runAsync(() -> {
            try {
                notifyEmployeesByWorkType(planId, plan, tenantId, userId);
            } catch (Exception e) {
                log.error("通知员工失败，计划ID: {}", planId, e);
            }
        });


        // 同步更新关联销售订单状态为生产中(7)
        if (plan.getOrderId() != null && !plan.getOrderId().isEmpty()) {
            try {

                // 获取当前登录用户
                LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                String operatorId = loginUser != null ? loginUser.getId() : null;
                // 获取当前订单状态，然后更新为生产中状态
                boolean updated = productSalesOrderService.updateOrderStatus(
                        plan.getOrderId(),
                        6, // 原状态 6待领料
                        7,    // 新状态：生产中
                        operatorId, // 操作人
                        "生产计划下发，订单进入生产阶段"
                );
                if (updated) {
                    log.info("生产计划{}下发成功，关联销售订单{}状态已更新为生产中", planId, plan.getOrderId());
                } else {
                    log.warn("生产计划{}下发成功，但更新关联销售订单{}状态失败", planId, plan.getOrderId());
                }
            } catch (Exception e) {
                log.error("生产计划{}下发时更新销售订单{}状态失败", planId, plan.getOrderId(), e);
                // 不抛出异常，避免影响生产计划下发流程
            }
        }

        log.info("生产计划{}下发成功", planId);
    }

    /**
     * 根据任务工种类型通知对应员工
     *
     * @param planId 生产计划ID
     * @param plan   生产计划对象
     */
    private void notifyEmployeesByWorkType(String planId, MesProductionPlan plan, String tenantId, String userId) {
        // 设置异步线程的安全上下文
        if (tenantId != null) {
            TenantContext.setTenant(tenantId);
        }

        // 1. 获取该计划下的所有任务
        List<MesProductionPlanTask> tasks = planTaskService.getTasksByPlanId(planId);
        if (tasks.isEmpty()) {
            log.info("生产计划{}下没有任务，无需通知员工", planId);
            return;
        }

        // 2. 获取所有涉及的工种类型
        List<String> workTypeIds = tasks.stream()
                .map(MesProductionPlanTask::getWorkTypeId)
                .filter(workTypeId -> workTypeId != null && !workTypeId.isEmpty())
                .distinct()
                .collect(Collectors.toList());

        if (workTypeIds.isEmpty()) {
            log.info("生产计划{}下的任务没有指定工种，无需通知员工", planId);
            return;
        }

        // 3. 根据工种获取对应的员工
        for (String workTypeId : workTypeIds) {
            try {
                // 查询该工种下的所有员工
                LambdaQueryWrapper<MesEmployeeWorkType> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(MesEmployeeWorkType::getWorkTypeId, workTypeId);
                List<MesEmployeeWorkType> employeeWorkTypes = employeeWorkTypeService.list(queryWrapper);

                if (employeeWorkTypes.isEmpty()) {
                    log.info("工种{}下没有分配员工，跳过通知", workTypeId);
                    continue;
                }

                // 获取员工ID列表
                List<String> employeeIds = employeeWorkTypes.stream()
                        .map(MesEmployeeWorkType::getEmployeeId)
                        .filter(employeeId -> employeeId != null && !employeeId.isEmpty())
                        .distinct()
                        .collect(Collectors.toList());

                if (!employeeIds.isEmpty()) {
                    // 发送通知消息
                    sendNotificationToEmployees(employeeIds, plan, workTypeId);
                }
            } catch (Exception e) {
                log.error("通知工种{}的员工失败", workTypeId, e);
            }
        }
    }

    /**
     * 发送通知消息给员工
     *
     * @param employeeIds 员工ID列表
     * @param plan        生产计划
     * @param workTypeId  工种ID
     */
    private void sendNotificationToEmployees(List<String> employeeIds, MesProductionPlan plan, String workTypeId) {
        try {
            // 构建通知消息  换行处理
            String title = "新生产任务通知";
            //计划编号、计划名称、计划产品数量、订单编号、计划开始时间、计划结束时间
            String content = String.format(
                    "<div style='font-family: Arial, sans-serif; line-height: 1.6; color: #333;'>" +
                            "<h3 style='color: #1890ff; margin-bottom: 15px;'>新生产任务通知</h3>" +
                            "<p style='margin-bottom: 15px;'>您好！有新的生产任务需要处理：</p>" +
                            "<div style='background: #f5f5f5; padding: 15px; border-radius: 6px; margin: 15px 0;'>" +
                            "<p style='margin: 8px 0;'><strong>计划编号：</strong>%s</p>" +
                            "<p style='margin: 8px 0;'><strong>计划名称：</strong>%s</p>" +
                            "<p style='margin: 8px 0;'><strong>计划产品数量：</strong>%s</p>" +
                            "<p style='margin: 8px 0;'><strong>关联订单编号：</strong>%s</p>" +
                            "<p style='margin: 8px 0;'><strong>计划开始时间：</strong>%s</p>" +
                            "<p style='margin: 8px 0;'><strong>计划结束时间：</strong>%s</p>" +
                            "</div>" +
                            "<p style='color: #52c41a; font-weight: bold; margin-top: 15px;'>请及时查看任务中心并领取相关任务。</p>" +
                            "</div>",
                    plan.getPlanNo() != null ? plan.getPlanNo() : "未设置",
                    plan.getPlanName() != null ? plan.getPlanName() : "未设置",
                    plan.getPlanQuantity() != null ? plan.getPlanQuantity().toString() : "未设置",
                    plan.getOrderNo() != null ? plan.getOrderNo() : "未设置",
                    plan.getPlanStartDate() != null ? plan.getPlanStartDate().toString() : "未设置",
                    plan.getPlanEndDate() != null ? plan.getPlanEndDate().toString() : "未设置"
            );

            // 创建系统通告对象
            SysAnnouncement announcement = new SysAnnouncement();
            announcement.setTitile(title);
            announcement.setMsgContent(content);
            announcement.setSender("系统");
            announcement.setPriority("M"); // 中等优先级
            announcement.setMsgType("2"); // 指定用户
            announcement.setSendStatus("1"); // 已发布
            announcement.setSendTime(new Date());
            announcement.setCancelTime(null);
            announcement.setDelFlag("0");

            // 设置接收用户ID（以逗号分隔，末尾加逗号）
            String userIds = String.join(",", employeeIds) + ",";
            announcement.setUserIds(userIds);

            // 保存通告
            sysAnnouncementService.saveAnnouncement(announcement);

            log.info("成功发送生产任务通知给工种{}的{}名员工，计划ID: {}", workTypeId, employeeIds.size(), plan.getId());

        } catch (Exception e) {
            log.error("发送通知消息失败，计划ID: {}, 工种ID: {}", plan.getId(), workTypeId, e);
            throw e;
        }
    }

    @Override
    public MesProductionPlanVO getPlanDetail(String planId) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            return null;
        }

        MesProductionPlanVO planVO = MesProductionPlanVO.fromEntity(plan);

        // 获取任务列表
        LambdaQueryWrapper<MesProductionPlanTask> taskQueryWrapper = new LambdaQueryWrapper<>();
        taskQueryWrapper.eq(MesProductionPlanTask::getPlanId, planId);
        taskQueryWrapper.orderByAsc(MesProductionPlanTask::getSequence);
        List<MesProductionPlanTask> tasks = planTaskService.list(taskQueryWrapper);
        //设置任务的参与人 计薪规则
        tasks.forEach(task -> {
            List<Object> mesTaskParticipantList = taskParticipantService.listObjs(new LambdaQueryWrapper<MesTaskParticipant>()
                    .eq(MesTaskParticipant::getTaskId, task.getId())
                    .select(MesTaskParticipant::getEmployeeName));
            //拼接任务参与者名称 ，分割
            task.setParticipantNames(StringUtils.join(mesTaskParticipantList, ","));

            MesPieceRateStandard pieceRateStandard = pieceRateStandardService.getById(task.getPieceRateStandardId());
            task.setPieceRateStandard(pieceRateStandard.getProductCategory() + "-￥" + pieceRateStandard.getBaseRate());
        });

        planVO.setTasks(tasks);

        // 计算进度和工时统计
        if (!tasks.isEmpty()) {
            // Work hour tracking removed

            // 计算完成进度
            long completedTasks = tasks.stream().filter(t -> t.getStatus() == 3).count();
            double progressPercentage = tasks.size() > 0 ? (double) completedTasks / tasks.size() * 100 : 0;
            planVO.setProgressPercentage(progressPercentage);
        }

        return planVO;
    }

    @Override
    public String generatePlanNo() {
        String dateStr = DateUtils.formatDate(new Date(), "yyyyMMdd");
        String prefix = "PLAN" + dateStr;

        // 查询当天最大序号
        LambdaQueryWrapper<MesProductionPlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.likeRight(MesProductionPlan::getPlanNo, prefix);
        queryWrapper.orderByDesc(MesProductionPlan::getPlanNo);
        queryWrapper.last("LIMIT 1");

        MesProductionPlan lastPlan = this.getOne(queryWrapper);

        int sequence = 1;
        if (lastPlan != null && lastPlan.getPlanNo() != null) {
            String lastPlanNo = lastPlan.getPlanNo();
            if (lastPlanNo.length() > prefix.length()) {
                try {
                    sequence = Integer.parseInt(lastPlanNo.substring(prefix.length())) + 1;
                } catch (NumberFormatException e) {
                    log.warn("解析计划编号序号失败：{}", lastPlanNo);
                }
            }
        }

        return prefix + String.format("%03d", sequence);
    }

    @Override
    public void updatePlanProgress(String planId) {
        // 获取计划的所有任务
        LambdaQueryWrapper<MesProductionPlanTask> taskQueryWrapper = new LambdaQueryWrapper<>();
        taskQueryWrapper.eq(MesProductionPlanTask::getPlanId, planId);
        List<MesProductionPlanTask> tasks = planTaskService.list(taskQueryWrapper);

        if (tasks.isEmpty()) {
            return;
        }

        // 统计任务状态
        long claimedTasks = tasks.stream().filter(t -> t.getStatus() >= 1).count();
        long inProgressTasks = tasks.stream().filter(t -> t.getStatus() == 2).count();
        long completedTasks = tasks.stream().filter(t -> t.getStatus() == 3).count();

        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            return;
        }

        // 更新计划状态
        int newStatus = plan.getStatus();
        if (completedTasks == tasks.size()) {
            newStatus = 5; // 已完成
        } else if (claimedTasks > 0) {
            newStatus = 4; // 进行中
        }

        if (newStatus != plan.getStatus()) {
            plan.setStatus(newStatus);
            this.updateById(plan);
        }
    }

    @Override
    public boolean checkEmployeeWorkTypePermission(String employeeId, String workTypeId) {
        LambdaQueryWrapper<MesEmployeeWorkType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MesEmployeeWorkType::getEmployeeId, employeeId);
        queryWrapper.eq(MesEmployeeWorkType::getWorkTypeId, workTypeId);
        queryWrapper.eq(MesEmployeeWorkType::getStatus, 1); // 启用状态

        return employeeWorkTypeService.count(queryWrapper) > 0;
    }

    @Override
    public List<ProductSalesOrder> getFinishedOrdersForInbound() {
        // 通过Mapper查询包装入库工种且状态为已完成的任务对应的订单
        return this.baseMapper.getFinishedOrdersForInbound();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createMergedPlan(MesMergedPlanCreateVO createVO) {
        try {
            // 1. 创建生产计划主记录
            MesProductionPlan plan = new MesProductionPlan();
            plan.setPlanName(createVO.getPlanName());
            plan.setPlanMode(1); // 合并计划模式
            plan.setPlanStartDate(createVO.getExpectedStartDate());
            plan.setPlanEndDate(createVO.getExpectedEndDate());
            plan.setStatus(0); // 待开始
            plan.setPriority(createVO.getPriority());
            plan.setRemark(createVO.getRemark());
            plan.setCreateTime(new Date());

            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if (loginUser != null) {
                plan.setCreateBy(loginUser.getUsername());
            }

            this.save(plan);

            // 2. 创建计划订单明细关联
            orderDetailService.batchCreatePlanOrderDetails(plan.getId(), createVO.getOrderDetailIds());

            // 3. 创建工种任务 - 按产品明细和工种组合生成具体任务
            if (createVO.getWorkTypes() != null && !createVO.getWorkTypes().isEmpty()
                    && createVO.getOrderDetailIds() != null && !createVO.getOrderDetailIds().isEmpty()) {

                // 获取选中的订单明细信息
                List<Map<String, Object>> orderDetails = orderDetailService.getOrderDetailsByIds(createVO.getOrderDetailIds());

                // 为每个产品明细和每个工种组合生成任务
                for (Map<String, Object> orderDetail : orderDetails) {
                    for (MesMergedPlanCreateVO.WorkTypeConfigVO workTypeVO : createVO.getWorkTypes()) {
                        MesProductionPlanTask task = new MesProductionPlanTask();
                        task.setPlanId(plan.getId());
                        task.setWorkTypeId(workTypeVO.getWorkTypeId());

                        // 设置产品明细关联信息
                        task.setOrderDetailId((String) orderDetail.get("orderDetailId"));
                        task.setOrderNo((String) orderDetail.get("orderNo"));
                        task.setProductInfo((String) orderDetail.get("productInfo"));
                        task.setProductCode((String) orderDetail.get("productCode"));
                        task.setProductName((String) orderDetail.get("productName"));
                        task.setProductSpec((String) orderDetail.get("productSpec"));

                        // 任务数量等于该产品明细的计划数量
                        task.setTaskQuantity((Integer) orderDetail.get("planQuantity"));
                        task.setCompletedQuantity(0);
                        task.setStatus(0); // 待领取
                        task.setCollaborationType(workTypeVO.getCollaborationType());
                        task.setMaxParticipants(workTypeVO.getMaxParticipants());
                        task.setCurrentParticipants(0);
                        task.setAllowPartialClaim(workTypeVO.getAllowPartialClaim());
                        task.setSequence(workTypeVO.getSequence());
                        task.setCreateTime(new Date());

                        if (loginUser != null) {
                            task.setCreateBy(loginUser.getUsername());
                        }

                        planTaskService.save(task);

                        log.info("创建任务: {} - {} (产品: {})", workTypeVO.getWorkTypeName(), orderDetail.get("productInfo"), orderDetail.get("planQuantity"));
                    }
                }
            }

            log.info("创建合并计划成功，计划ID: {}", plan.getId());
            return plan.getId();

        } catch (Exception e) {
            log.error("创建合并计划失败", e);
            throw new JeecgBootException("创建合并计划失败: " + e.getMessage());
        }
    }

    @Override
    public MesProductionPlanDetailVO getDetailedPlan(String planId) {
        try {
            // 1. 获取计划基本信息
            MesProductionPlan plan = this.getById(planId);
            if (plan == null) {
                return null;
            }

            MesProductionPlanDetailVO detailVO = new MesProductionPlanDetailVO();
            detailVO.setPlan(plan);

            // 2. 获取关联的订单明细
            List<MesProductionPlanOrderDetail> orderDetails = planOrderDetailService.getOrderDetailsByPlanId(planId);
            detailVO.setOrderDetails(orderDetails);

            // 3. 获取计划任务列表
            LambdaQueryWrapper<MesProductionPlanTask> taskQuery = new LambdaQueryWrapper<>();
            taskQuery.eq(MesProductionPlanTask::getPlanId, planId);
            List<MesProductionPlanTask> tasks = planTaskService.list(taskQuery);
            // 4. 转换任务列表为VO格式并获取参与者信息
            List<MesProductionPlanDetailVO.TaskWithParticipantsVO> taskVOs = new ArrayList<>();
            if (tasks != null && !tasks.isEmpty()) {
                for (MesProductionPlanTask task : tasks) {
                    MesProductionPlanDetailVO.TaskWithParticipantsVO taskVO = new MesProductionPlanDetailVO.TaskWithParticipantsVO();
                    taskVO.setTaskInfo(task);

                    List<MesTaskParticipant> participants = taskParticipantService.getTaskParticipants(task.getId());
                    taskVO.setParticipants(participants);

                    taskVOs.add(taskVO);
                }
            }
            detailVO.setTasks(taskVOs);

            // 5. 计算统计信息
            detailVO.setTotalOrderDetails(orderDetails != null ? orderDetails.size() : 0);
            detailVO.setTotalTasks(tasks != null ? tasks.size() : 0);

            int totalParticipants = 0;
            if (tasks != null) {
                for (MesProductionPlanTask task : tasks) {
                    totalParticipants += task.getCurrentParticipants() != null ? task.getCurrentParticipants() : 0;
                }
            }
            detailVO.setTotalParticipants(totalParticipants);

            return detailVO;

        } catch (Exception e) {
            log.error("获取计划详细信息失败", e);
            throw new JeecgBootException("获取计划详细信息失败: " + e.getMessage());
        }
    }

    @Override
    public boolean canAddOrderDetailsToPlan(String planId, List<String> orderDetailIds) {
        try {
            // 1. 检查计划是否存在且状态允许添加
            MesProductionPlan plan = this.getById(planId);
            if (plan == null) {
                return false;
            }

            // 只有待开始和进行中的计划可以添加订单明细
            if (plan.getStatus() != 0 && plan.getStatus() != 1) {
                return false;
            }

            // 2. 检查订单明细是否已经关联到其他计划
            return planOrderDetailService.canAddOrderDetailsToPlan(planId, orderDetailIds);

        } catch (Exception e) {
            log.error("检查订单明细失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrderDetailsToPlan(String planId, List<String> orderDetailIds) {
        try {
            // 1. 先检查是否可以添加
            if (!canAddOrderDetailsToPlan(planId, orderDetailIds)) {
                return false;
            }

            // 2. 批量创建关联记录
            return planOrderDetailService.batchCreatePlanOrderDetails(planId, orderDetailIds);

        } catch (Exception e) {
            log.error("添加订单明细到计划失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeOrderDetailsFromPlan(String planId, List<String> orderDetailIds) {
        try {
            return planOrderDetailService.removeOrderDetailsFromPlan(planId, orderDetailIds);
        } catch (Exception e) {
            log.error("从计划中移除订单明细失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void claimPlan(String planId, String employeeId, String remark) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (plan.getStatus() != 2) {
            throw new JeecgBootException("只有已下发的计划才能被领取");
        }

        if (plan.getClaimedBy() != null && !plan.getClaimedBy().isEmpty()) {
            throw new JeecgBootException("该计划已被其他人领取");
        }

        // 更新计划状态
        plan.setClaimedBy(employeeId);
        plan.setStatus(3); // 进行中状态
        plan.setClaimedTime(new Date());
        plan.setUpdateTime(new Date());
        if (remark != null && !remark.trim().isEmpty()) {
            plan.setRemark(remark);
        }

        this.updateById(plan);
        log.info("生产计划领取成功，计划ID: {}, 员工ID: {}", planId, employeeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startPlan(String planId, String employeeId) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (!employeeId.equals(plan.getClaimedBy())) {
            throw new JeecgBootException("只能开始自己领取的计划");
        }

        if (plan.getStatus() != 3 && plan.getStatus() != 4) {
            throw new JeecgBootException("只有进行中或已暂停的计划才能开始");
        }

        // 更新计划状态
        plan.setStatus(3); // 进行中状态
        plan.setUpdateTime(new Date());

        this.updateById(plan);
        log.info("生产计划开始成功，计划ID: {}, 员工ID: {}", planId, employeeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pausePlan(String planId, String employeeId) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (!employeeId.equals(plan.getClaimedBy())) {
            throw new JeecgBootException("只能暂停自己领取的计划");
        }

        if (plan.getStatus() != 3) {
            throw new JeecgBootException("只有进行中的计划才能暂停");
        }

        // 更新计划状态
        plan.setStatus(4); // 已暂停状态
        plan.setUpdateTime(new Date());

        this.updateById(plan);
        log.info("生产计划暂停成功，计划ID: {}, 员工ID: {}", planId, employeeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resumePlan(String planId, String employeeId) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (!employeeId.equals(plan.getClaimedBy())) {
            throw new JeecgBootException("只能恢复自己领取的计划");
        }

        if (plan.getStatus() != 4) {
            throw new JeecgBootException("只有已暂停的计划才能恢复");
        }

        // 更新计划状态
        plan.setStatus(3); // 进行中状态
        plan.setUpdateTime(new Date());

        this.updateById(plan);
        log.info("生产计划恢复成功，计划ID: {}, 员工ID: {}", planId, employeeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completePlan(String planId, String employeeId, Integer completedQuantity, Double actualHours, String remark) {
        MesProductionPlan plan = this.getById(planId);
        if (plan == null) {
            throw new JeecgBootException("生产计划不存在");
        }

        if (!employeeId.equals(plan.getClaimedBy())) {
            throw new JeecgBootException("只能完成自己领取的计划");
        }

        if (plan.getStatus() != 3 && plan.getStatus() != 4) {
            throw new JeecgBootException("只有进行中或已暂停的计划才能完成");
        }

        // 更新计划状态
        plan.setStatus(5); // 已完成状态
        plan.setUpdateTime(new Date());

        if (completedQuantity != null && completedQuantity > 0) {
            plan.setActualQuantity(completedQuantity);
        }

        if (remark != null && !remark.trim().isEmpty()) {
            plan.setRemark(remark);
        }

        this.updateById(plan);
        log.info("生产计划完成成功，计划ID: {}, 员工ID: {}, 完成数量: {}", planId, employeeId, completedQuantity);
    }

    @Override
    public IPage<MesProductionPlan> getPlansByTaskOwnership(String employeeId, Integer planStatus, Integer pageNo, Integer pageSize) {
        Page<MesProductionPlan> page = new Page<>(pageNo, pageSize);
        //根据 MesTaskParticipant 获取当前用户参与的任务 根据任务获取计划
        List<Object> taskIds = taskParticipantService.listObjs(new LambdaQueryWrapper<MesTaskParticipant>()
                        .select(MesTaskParticipant::getTaskId)
                        .eq(MesTaskParticipant::getEmployeeId, employeeId))
                .stream()
                .distinct()
                .collect(Collectors.toList());
        List<Object> planIds = planTaskService.listObjs(new LambdaQueryWrapper<MesProductionPlanTask>()
                        .select(MesProductionPlanTask::getPlanId)
                        .in(MesProductionPlanTask::getId, taskIds))
                .stream()
                .distinct()
                .collect(Collectors.toList());


        // 通过任务表查询员工参与的计划
        return baseMapper.getPlansByTaskOwnership(page, planIds, planStatus);
    }
}
